package com.funsport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.funsport.entity.*;
import com.funsport.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;

/**
 * 积分奖励服务实现
 *
 * @author Fun-Sport Team
 */
@Slf4j
@Service
public class PointRewardServiceImpl implements IPointRewardService {
    
    @Autowired
    private IUserService userService;
    
    @Autowired
    private IPointRecordService pointRecordService;
    
    @Autowired
    private IEventService eventService;
    
    @Autowired
    private ICommunityPostService communityPostService;
    
    // 积分规则常量
    private static final int POINTS_EVENT_NORMAL = 15;      // 参与活动基础积分
    private static final int POINTS_EVENT_LONG = 20;        // 长时间活动积分（超2小时）
    private static final int POINTS_FIRST_POST = 10;        // 第一次发布帖子
    private static final int POINTS_POST_LIKE = 3;          // 帖子被点赞
    private static final int POINTS_POST_FAVORITE = 3;      // 帖子被收藏
    private static final int POINTS_POST_COMMENT = 3;       // 帖子被回复
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rewardForEventCheckIn(Long userId, Long eventId) {
        if (userId == null || eventId == null) {
            log.warn("活动签到奖励失败：userId或eventId为空");
            return;
        }
        
        try {
            // 查询活动信息
            Event event = eventService.getById(eventId);
            if (event == null) {
                log.warn("活动签到奖励失败：活动不存在, eventId={}", eventId);
                return;
            }
            
            // 检查是否已经奖励过积分
            long count = pointRecordService.count(
                new LambdaQueryWrapper<PointRecord>()
                    .eq(PointRecord::getUserId, userId)
                    .eq(PointRecord::getRelatedEventId, eventId)
                    .eq(PointRecord::getPointType, "event_checkin")
            );
            
            if (count > 0) {
                log.info("活动签到奖励跳过：已经奖励过积分, userId={}, eventId={}", userId, eventId);
                return;
            }
            
            // 计算活动时长
            int points = POINTS_EVENT_NORMAL;
            String description = "参与活动奖励";
            
            if (event.getStartTime() != null && event.getEndTime() != null) {
                Duration duration = Duration.between(event.getStartTime(), event.getEndTime());
                long hours = duration.toHours();
                
                if (hours >= 2) {
                    points = POINTS_EVENT_LONG;
                    description = "参与长时间活动奖励（超2小时）";
                }
            }
            
            // 增加用户积分
            addPoints(userId, points, "event_checkin", "活动签到", description, eventId, null);
            
            log.info("活动签到奖励成功：userId={}, eventId={}, points={}", userId, eventId, points);
        } catch (Exception e) {
            log.error("活动签到奖励失败：userId={}, eventId={}", userId, eventId, e);
            throw e;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rewardForPostPublish(Long userId, Long postId) {
        if (userId == null || postId == null) {
            log.warn("发布帖子奖励失败：userId或postId为空");
            return;
        }
        
        try {
            // 检查是否是第一次发布帖子
            long postCount = communityPostService.count(
                new LambdaQueryWrapper<CommunityPost>()
                    .eq(CommunityPost::getAuthorId, userId)
            );
            
            if (postCount != 1) {
                log.info("发布帖子奖励跳过：不是第一次发布帖子, userId={}, postId={}, postCount={}", 
                    userId, postId, postCount);
                return;
            }
            
            // 检查是否已经奖励过积分
            long rewardCount = pointRecordService.count(
                new LambdaQueryWrapper<PointRecord>()
                    .eq(PointRecord::getUserId, userId)
                    .eq(PointRecord::getPointType, "first_post")
            );
            
            if (rewardCount > 0) {
                log.info("发布帖子奖励跳过：已经奖励过第一次发帖积分, userId={}, postId={}", userId, postId);
                return;
            }
            
            // 增加用户积分
            addPoints(userId, POINTS_FIRST_POST, "first_post", "首次发布帖子", 
                "恭喜你发布了第一条帖子！", null, null);
            
            log.info("发布帖子奖励成功：userId={}, postId={}, points={}", userId, postId, POINTS_FIRST_POST);
        } catch (Exception e) {
            log.error("发布帖子奖励失败：userId={}, postId={}", userId, postId, e);
            throw e;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rewardForPostLike(Long postOwnerId, Long postId, Long likerId) {
        if (postOwnerId == null || postId == null || likerId == null) {
            log.warn("帖子点赞奖励失败：参数为空");
            return;
        }
        
        // 不能给自己点赞获得积分
        if (postOwnerId.equals(likerId)) {
            log.info("帖子点赞奖励跳过：不能给自己点赞获得积分, postOwnerId={}, likerId={}", postOwnerId, likerId);
            return;
        }
        
        try {
            // 增加帖子作者积分
            addPoints(postOwnerId, POINTS_POST_LIKE, "post_like", "帖子被点赞", 
                "你的帖子收到了点赞！", null, null);
            
            log.info("帖子点赞奖励成功：postOwnerId={}, postId={}, likerId={}, points={}", 
                postOwnerId, postId, likerId, POINTS_POST_LIKE);
        } catch (Exception e) {
            log.error("帖子点赞奖励失败：postOwnerId={}, postId={}, likerId={}", 
                postOwnerId, postId, likerId, e);
            throw e;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rewardForPostFavorite(Long postOwnerId, Long postId, Long collectorId) {
        if (postOwnerId == null || postId == null || collectorId == null) {
            log.warn("帖子收藏奖励失败：参数为空");
            return;
        }
        
        // 不能给自己收藏获得积分
        if (postOwnerId.equals(collectorId)) {
            log.info("帖子收藏奖励跳过：不能给自己收藏获得积分, postOwnerId={}, collectorId={}", 
                postOwnerId, collectorId);
            return;
        }
        
        try {
            // 增加帖子作者积分
            addPoints(postOwnerId, POINTS_POST_FAVORITE, "post_favorite", "帖子被收藏", 
                "你的帖子被收藏了！", null, null);
            
            log.info("帖子收藏奖励成功：postOwnerId={}, postId={}, collectorId={}, points={}", 
                postOwnerId, postId, collectorId, POINTS_POST_FAVORITE);
        } catch (Exception e) {
            log.error("帖子收藏奖励失败：postOwnerId={}, postId={}, collectorId={}", 
                postOwnerId, postId, collectorId, e);
            throw e;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rewardForPostComment(Long postOwnerId, Long postId, Long commentId) {
        if (postOwnerId == null || postId == null || commentId == null) {
            log.warn("帖子回复奖励失败：参数为空");
            return;
        }
        
        try {
            // 增加帖子作者积分（评论者不获得积分，只有被评论者获得）
            addPoints(postOwnerId, POINTS_POST_COMMENT, "post_comment", "帖子被回复", 
                "你的帖子收到了新的回复！", null, null);
            
            log.info("帖子回复奖励成功：postOwnerId={}, postId={}, commentId={}, points={}", 
                postOwnerId, postId, commentId, POINTS_POST_COMMENT);
        } catch (Exception e) {
            log.error("帖子回复奖励失败：postOwnerId={}, postId={}, commentId={}", 
                postOwnerId, postId, commentId, e);
            throw e;
        }
    }
    
    /**
     * 增加用户积分
     */
    private void addPoints(Long userId, int points, String pointType, String reason, 
                          String description, Long relatedEventId, Long relatedClubId) {
        if (points <= 0) {
            log.warn("积分值无效：points={}", points);
            return;
        }
        
        // 更新用户积分
        User user = userService.getById(userId);
        if (user == null) {
            log.warn("用户不存在：userId={}", userId);
            return;
        }
        
        int currentPoints = user.getPoints() != null ? user.getPoints() : 0;
        user.setPoints(currentPoints + points);
        userService.updateById(user);
        
        // 创建积分记录
        PointRecord record = new PointRecord();
        record.setUserId(userId);
        record.setPointsChange(points);
        record.setPointType(pointType);
        record.setReason(reason);
        record.setDescription(description);
        record.setRelatedEventId(relatedEventId);
        record.setRelatedClubId(relatedClubId);
        pointRecordService.save(record);
        
        log.info("积分增加成功：userId={}, points={}, pointType={}, newTotal={}", 
            userId, points, pointType, user.getPoints());
    }
}

